﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Brain.SunBurn;
using SynapseGaming.LightingSystem.Core;

namespace Brain
{
    public class SunBurnStereoscopicManager : IStereoscopicManager
    {
        private StereoMode stereoMode;
        public StereoMode StereoMode
        {
            get { return stereoMode; }
            set { stereoMode = value; Load(); }
        }

        public bool Invert { get; set; }

        public float EyeDistance = 1;

        private RenderTargetHelper leftTarget;
        private RenderTargetHelper rightTarget;
        private FrameBuffers stereoBuffers;
        private Vector2 LeftPosition;
        private Vector2 RightPosition;

        private SpriteBatch mBatch;

        private void Load()
        {
            if (leftTarget != null)
            {
                Texture2D tex = leftTarget.GetTexture();
                if (tex != null && !tex.IsDisposed)
                {
                    tex.Dispose();
                }
            }
            if (rightTarget != null)
            {
                Texture2D tex = rightTarget.GetTexture();
                if (tex != null && !tex.IsDisposed)
                {
                    tex.Dispose();
                }
            }
            if (mBatch != null && !mBatch.IsDisposed)
            {
                mBatch.Dispose();
            }

            if (stereoMode != Brain.StereoMode.NoStereo)
            {
                Vector2 leftSize, rightSize;

                GraphicsDevice device = Engine.Instance.GraphicsDevice;
                PresentationParameters pp = device.PresentationParameters;
                StereoscopicUtil.GetFrames(pp.BackBufferWidth,
                    pp.BackBufferHeight,
                    this.stereoMode,
                    out leftSize, out LeftPosition,
                    out rightSize, out RightPosition);

                leftTarget = new RenderTargetHelper(RenderTargetHelper.TargetType.Standard, 
                    (int)leftSize.X, (int)leftSize.Y,
                    SurfaceFormat.Color);
                rightTarget = new RenderTargetHelper(RenderTargetHelper.TargetType.Standard,
                    (int)rightSize.X, (int)rightSize.Y,
                    SurfaceFormat.Color);

                stereoBuffers = new FrameBuffers(
                    (int)leftSize.X, (int)leftSize.Y,
                    DetailPreference.High, DetailPreference.High);

                SunBurnRenderManager3D render = Engine.Instance.RenderManager3D as SunBurnRenderManager3D;
                render.SceneInterface.ResourceManager.AssignOwnership(leftTarget);
                render.SceneInterface.ResourceManager.AssignOwnership(rightTarget);
                render.SceneInterface.ResourceManager.AssignOwnership(stereoBuffers);


                mBatch = new SpriteBatch(device);
            }
        }

        public void Draw(ICamera3D Camera, IRenderManager3D renderManager)
        {
            GraphicsDevice device = Engine.Instance.GraphicsDevice;

            SunBurnRenderManager3D render = Engine.Instance.RenderManager3D as SunBurnRenderManager3D;

            render.SceneState.BeginFrameRendering(Camera.View, Camera.Projection,
                Engine.Instance.GameTime, render.Environment,
                stereoBuffers, render.RenderingToScreen);
            leftTarget.BeginFrameRendering(render.SceneState);
            render.RenderTarget(this.leftTarget);

            leftTarget.EndFrameRendering();
            render.SceneState.EndFrameRendering();

            Vector3 right = Camera.View.Right * EyeDistance;
            Vector3 newPos = Camera.Position + right;
            Vector3 newTarget = Camera.Target + right;
            Matrix newView = Matrix.CreateLookAt(newPos, newTarget, Camera.Up);

            render.SceneState.BeginFrameRendering(newView, Camera.Projection,
                Engine.Instance.GameTime, render.Environment,
                stereoBuffers, render.RenderingToScreen);
            rightTarget.BeginFrameRendering(render.SceneState);
            render.RenderTarget(this.rightTarget);

            rightTarget.EndFrameRendering();
            render.SceneState.EndFrameRendering();

            DrawFrames();
        }

        public void Reset()
        {
        }

        public SerializationData Data { get; set; }

        public void SerializeData(DefaultSerializationManager manager)
        {
        }

        public void DeserializeData(DefaultSerializationManager manager, SerializationData newData)
        {
        }


        public void Draw(IRenderManager2D renderManager)
        {
        }

        private void DrawFrames()
        {
            mBatch.Begin();
            if (Invert)
            {
                mBatch.Draw(leftTarget.GetTexture(), this.RightPosition, Color.White);
                mBatch.Draw(rightTarget.GetTexture(), this.LeftPosition, Color.White);
            }
            else
            {
                mBatch.Draw(leftTarget.GetTexture(), this.LeftPosition, Color.White);
                mBatch.Draw(rightTarget.GetTexture(), this.RightPosition, Color.White);
            }
            mBatch.End();
        }


        public void DeserializedAll()
        {
        }
    }
}
